package com.android.webrtc.audio;

import android.util.Log;

public class NoiseSuppression {
	static {
        System.loadLibrary("webrtc_aecm"); // to load the libwebrtc_aecm.so library.
    }
	public static final int NS_MILD = 0;
	public static final int NS_MEDIUM = 1;
	public static final int NS_HIGH = 2;
	
	private int nsHandle = 0;
	private int freq = 80;
	
	public NoiseSuppression (int level, int freq) throws Exception {
		if (level != NS_MILD && level != NS_MEDIUM &&
				level != NS_HIGH)
			throw new IllegalArgumentException("Argument error");
		
		try {
			this.nsHandle = nsCreate();
			if (-1 == nsHandle)
				throw new Exception("Cannot create instance");
			if (-1 == nsInit(this.nsHandle, freq))
				throw new Exception("Cannot init");
			if (-1 == nsSetPolicy(this.nsHandle, level))
				throw new Exception("Cannot set mode");
			this.freq = freq;
		} catch (Exception e) {
			if (nsHandle > 0)
				nsFree(this.nsHandle);
			throw e;
		}
	}
	
	// For 8000 frequent, frame length should be multipol of 80
	// For 16000 / 32000, frame length should be multipo of 160
	public void process(short []spframe, short []outframe) throws Exception {
		if (0 == this.nsHandle)
			throw new IllegalStateException("Null handle");
		
		int cellLength = 160;
		if (this.freq == 8000)
			cellLength = 80;
		int res = nsProcess(this.nsHandle, spframe, null, outframe, null,
				spframe.length, cellLength);
		if (-1 == res)
			throw new Exception("Process failed " + res);
	}
	
	public void close() {
		if (0 == this.nsHandle)
			return;
		
		int res = nsFree(this.nsHandle);
		if (-1 == res)
			Log.e("NoiseSuppression", "Cannot free handle at " + this.nsHandle + " : " + res);
		this.nsHandle = 0;
	}
	
	@Override
	protected void finalize() throws Throwable {
		super.finalize();
	
		if (this.nsHandle > 0)
			nsFree(this.nsHandle);
	}
	
	private static native int nsCreate();
	private static native int nsFree(int nsHandle);
	private static native int nsInit(int nsHandle, int freq);
	private static native int nsSetPolicy(int nsHandle, int mode);
	private static native int nsProcess(int nsHandle, short []spframe,
			short []spframe_H, short []outframe, short []outframe_H,
			int frameLength, int cellLength);
	private static native float nsPriorSpeechProbability(int nsHandle);
}
